#include "example.h"
using namespace py::literals;

Pet::Pet(const std::string &name, Kind kind) {
    this->name = name;
    type = kind;
}

void Pet::set_name(const std::string &name_) {
    this->name = name_;
}

std::string Pet::get_name() const {
    return this->name;
}

Data *Pet::add(int &x, int &y) {
    Data *data = new Data;
    data->x = x;
    data->y = y;
    return data;
}

void Pet::print_dict(const py::dict &dic) {
    for (auto item: dic) {
        std::cout << std::string(py::str(item.first)) << std::endl;
        std::cout << std::string(py::str(item.second)) << std::endl;
    }
}

std::string invoked() {

    py::object scipy = py::module_::import("scipy");
    return std::string(py::str(scipy.attr("__version__")));


}

PYBIND11_MODULE(example, m) {
    m.doc() = "class test";
    py::class_<Pet> pet(m, "Pet", py::dynamic_attr());
    pet.def(py::init<const std::string &, Pet::Kind>())
            .def("get_name", &Pet::get_name)
            .def("set_name", &Pet::set_name, py::arg("name"))
            .def_readwrite("name", &Pet::name)
            .def_readwrite("type", &Pet::type)
            .def("add", &Pet::add, py::arg("x") = 1, py::arg("y") = 2, py::return_value_policy::reference)
            .def("print_dict", &Pet::print_dict)
            .def_readwrite("attr", &Pet::atr)
            .def("__repr__", [](const Pet &pet) {
                return "<example.Pet named '" + pet.get_name() + "'>";
            });
    py::enum_<Pet::Kind>(pet, "Kind")
            .value("Dog", Pet::Kind::Dog)
            .value("Cat", Pet::Kind::Cat)
            .export_values();
    py::class_<Pet::Attr>(pet, "Attr")
            .def(py::init<>())
            .def_readwrite("a", &Pet::Attr::a);
    py::class_<Data> data(m, "Data");
    data.def_readwrite("x", &Data::x)
            .def_readwrite("y", &Data::y)
            .def("__repr__", [](const Data &data) {

                return "<Data final result  is '" + std::to_string(data.x + data.y) + "'>";

            });
    m.def("print_utf8", [](std::string &s) {

        std::cout << "utf-8 is icing on the cake.\n";
        std::cout << s;
    }, "a test of std::string ");
    m.def("print_", [](const char *s) {
        std::cout << "utf-8 is icing on the cake.\n";
        std::cout << s;
    }, "const char* test");
    m.def("return_bytes", []() {
        std::string s("\xba\xd0\xba\xd0");
        return s;
    });
    m.def("append_vel", [](std::vector<int> &v) {
        v.push_back(1);
    });
    m.def("invoked", &invoked);

}

int main() {
    py::scoped_interpreter guard{};
    py::module_ np = py::module_::import("numpy");
    auto res = np.attr("zeros((5,6))")();
    std::cout<<res<<std::endl;
}



